<?php
namespace App\Repository\Db;

use App\Exceptions\ValidateException;
use App\Model\MemberIntegral;
use App\Model\MemberRecharge;
use App\Model\Setting;
use App\Model\Shopping;
use App\Repository\Contracts\GoodsInterface;
use App\Repository\Contracts\MemberIntegralInterface;
use App\Repository\Contracts\MemberInterface;
use App\Repository\Contracts\MemberRechargeInterface;
use App\Repository\Contracts\RefundShoppingInterface;
use App\Repository\Contracts\SettingInterface;
use App\Repository\Contracts\ShoppingCartInterface;
use App\Repository\Contracts\ShoppingInterface;
use App\Repository\Contracts\ShoppingJavaInterface;
use Illuminate\Support\Facades\DB;

/**
 * @Author:: HuangYin
 * @DateTime: 2017-01-16 15:04
 *
 * @Description:
 */
class ShoppingRepository extends Repository implements ShoppingInterface
{
    protected $rules = [
        'created' => [
            'admin_id' => 'required|exists:admin,uid',
            'store_id' => 'required',
            'card_amount' => 'sometimes|required',
            'amount' => 'sometimes|required',
            'pay_type' => 'required|integer',
            'member_id' => 'sometimes|exists:member,uid',
            'auth_code' => 'sometimes|min:8|max:20'
        ]
    ];

    protected $messages = [
        'admin_id.required' => "管理员不能为空",
        'admin_id.exists' => "管理员 ID 不存在",
        'store_id.required' => "门店 ID 不能为空",
        'card_amount.required' => "卡片金额不能为空",
        'amount.required' => "金额不能为空",
        'pay_type.required' => "支付方式不能为空",
        'member_id.exists' => "会员 ID 不存在",
        'auth_code.min' => "付款码不能小于 16 字",
        'auth_code.max' => "付款码不能超过 20 字"
    ];

    protected function modelName()
    {
        return 'App\Model\Shopping';
    }

    public function lists($limit, $page, $map = [])
    {
        $query = $this->searchMap($map);
        $total = $query->count();
        $data = $query->orderBy('id', 'desc')->with('member')->simplePaginate($limit, ['*'], 'page', $page);
        $list = [];
        foreach ($data as $key => $val) {
            $list[$key] = $val;
            $list[$key]['username'] = $val['uid'] ? $val->member->real_name : '';
        }

        return $this->simplePaginate('list', $list, $total, ceil($total / $limit), $page);
    }

    public function detail($map = [])
    {
        $result = [];
        $data = $this->searchMap($map)->with('detail')->first();
        if ($data) {
            $result = $data->toArray();
            $result['detail'] = $data->detail->toArray();
        }

        return $result;
    }

    public function created(array $data)
    {
        $this->validate($data, 'created');
        try {
            // 开启事物
            DB::beginTransaction();
            $time = time();
            // 读取购物车所有信息
            $memberId = $data['member_id'] ?: 0;
            $authCode = $data['auth_code'] ? $data['auth_code'] : 0;
            $outTradeNo = $data['out_trade_no'] ? $data['out_trade_no'] : date('mdHis') . mt_rand(100, 1000);
            $tradeNo = $data['trade_no'] ? $data['trade_no'] : 0;
            $shoppingCart = $this->container->make(ShoppingCartInterface::class)->lists([
                ['field' => 'uid', 'value' => $memberId, 'operation' => '='],
                ['field' => 'admin_id', 'value' => $data['admin_id'], 'operation' => '='],
                ['field' => 'status', 'value' => 1, 'operation' => '=']
            ]);
            if (!$shoppingCart) {
                throw new ValidateException('购物车没有商品');
            }
            // 写入购物表
            $shoppingData = [
                'uid' => $memberId, 'out_trade_no' => $outTradeNo, 'auth_code' => $authCode,
                'trade_no' => $tradeNo, 'card_amount' => round($data['card_amount'], 2),
                'amount' => round($data['amount'], 2), 'pay_type' => $data['pay_type'],
                'pay_status' => 1, 'admin_id' => $data['admin_id']
            ];
            $shoppingId = $this->save($shoppingData);
            // 写入购物详情表
            $shoppingDetail = $inventory = [];
            $totalAmount = 0;
            foreach ($shoppingCart as $val) {
                $shoppingDetail[] = [
                    'shopping_id' => $shoppingId, 'goods_id' => $val['goods_id'], 'zh_name' => $val['zh_name'],
                    'en_name' => $val['en_name'], 'price' => $val['price'], 'counts' => $val['counts'],
                    'created_at' => $time, 'article_no' => $val['article_no'], 'updated_at' => $time
                ];
                $inventory[] = ['goods_id' => $val['goods_id'], 'counts' => $val['counts']];
                $totalAmount += $val['price'] * $val['counts'];
            }
            if (bccomp($totalAmount, ($data['amount'] + $data['card_amount']), 2)) {
                throw new ValidateException('非法操作');
            }
            if (!DB::table('shopping_detail')->insert($shoppingDetail)) {
                throw new ValidateException('操作失败');
            }
            // 会员
            if ($memberId) {
                // 会员卡消费变更
                if ($data['card_amount'] > 0) {
                    $memberRecharge = $this->container->make(MemberInterface::class)->detail($memberId);
                    if ($memberRecharge['money'] >= round($data['card_amount'], 2)) {
                        $recharge = [
                            'uid' => $memberId, 'store_id' => $data['store_id'], 'admin_id' => $data['admin_id'],
                            'type' => MemberRecharge::SPENDING, 'money' => -round($data['card_amount'], 2)
                        ];
                        $this->container->make(MemberRechargeInterface::class)->created($recharge);
                    } else {
                        throw new ValidateException('卡内余额不足');
                    }
                }
                // 积分变更
                $integral = [
                    'uid' => $memberId, 'store_id' => $data['store_id'], 'type' => MemberIntegral::SPENDING,
                    'integral' => round($data['card_amount'] + $data['amount'], 2)
                ];
                $this->container->make(MemberIntegralInterface::class)->created($integral);
            }
            // 库存处理
            $this->container->make(GoodsInterface::class)->updateInventory($inventory);
            // 清空订单车
            $this->container->make(ShoppingCartInterface::class)->clear($data['admin_id']);
            // 关闭事务
            DB::commit();
            return $outTradeNo;
        } catch (ValidateException $e) {
            throw new ValidateException($e->getMessage());
        }
    }

    public function sync($storeId)
    {
        if (env('DIRECT_SALE') && env('JAVA_NETWORK')) {
            $data = $this->model->where('status', '=', 2)->with('detail')->get();
            $ids = [];
            foreach ($data as $val) {
                $ids[] = $val->id;
                $this->container->make(ShoppingJavaInterface::class)->syncShopping($storeId, $val->toArray());
                sleep(2);
            }
            $this->model->whereIn('id', $ids)->update(['status' => 3]);
        }

        return true;
    }

    public function syncAmount($storeId)
    {
        if (env('DIRECT_SALE') && env('JAVA_NETWORK')) {
            $data = $this->model->where('status', '=', 1)->get();
            $ids = [];
            foreach ($data as $val) {
                $ids[] = $val->id;
                $this->container->make(ShoppingJavaInterface::class)->syncShoppingAmount($storeId, $val->toArray());
                sleep(2);
            }
            $this->model->whereIn('id', $ids)->update(['status' => 2]);
        }

        return true;
    }

    public function listBy($shoppingId, $goodsIds = [])
    {
        $data = $this->setModel('App\Model\ShoppingDetail')->where('shopping_id', '=', $shoppingId)
            ->whereIn('goods_id', $goodsIds)->get()->toArray();
        $result = [];
        foreach ($data as $val) {
            $result[$val['goods_id']] = $val;
        }

        return $result;
    }

    public function statistic($uid, $startTime)
    {
        $endTime = time();
        $map = [
            ['field' => 'admin_id', 'value' => $uid, 'operation' => '='],
            ['field' => 'created_at', 'value' => strtotime($startTime), 'operation' => '>='],
            ['field' => 'created_at', 'value' => $endTime, 'operation' => '<=']
        ];
        $shopping = $this->getShopping($map);
        $refund = $this->getRefund($map);
        $recharge = $this->getRecharge($map);
        $storeConfig = json_decode(app(SettingInterface::class)->findByName(Setting::STORE_CONFIG)['config'], true);
        $result['userInfo'] = [
            'storeName' => $storeConfig['storeName'], 'endTime' => date('Y-m-d H:i:s', $endTime),
            'startTime' => date('Y-m-d H:i:s', strtotime($startTime))
        ];

        return array_merge($shopping, $refund, $recharge, $result);
    }

    /**
     * 获取购物数据
     *
     * @param $map
     * @return array
     */
    protected function getShopping($map)
    {
        $payType = $goodsType = $payData = $goodsData = $data = [];
        $resource = $this->searchMap($map)->with('detail')->get()->toArray();
        foreach ($resource as $value) {
            if ($value['card_amount'] > 0) {
                $payData[Shopping::MEMBER_CARD][] = $value['card_amount'];
            }
            $payData[$value['pay_type']][] = $value['amount'];
            $goodsData[] = $value['detail'];
        }
        foreach ($payData as $keys => $pay) {
            $key = $this->getPayType($keys);
            $payType[$key] = array_sum($pay);
        }
        foreach ($goodsData as $goods) {
            foreach ($goods as $good) {
                $data[$good['goods_id']][] = [
                    'name' => $good['zh_name'], 'counts' => $good['counts'],
                    'totalPrice' => $good['price'] * $good['counts']
                ];
            }
        }
        $totalCount = 0;
        foreach ($data as $k => $val) {
            $amount[$k] = $counts[$k] = 0;
            $name[$k] = $val[0]['name'];
            foreach ($val as $v) {
                $amount[$k] += $v['totalPrice'];
                $counts[$k] += $v['counts'];
            }
            $totalCount += $counts[$k];
            $goodsType[] = [
                'name' => $name[$k], 'amount' => $amount[$k], 'counts' => $counts[$k]
            ];
        }

        return ['goodsType' => $goodsType, 'payType' => $payType, 'totalCount' => $totalCount];
    }

    /**
     * 获取退货数据
     *
     * @param $map
     * @return array
     */
    protected function getRefund($map)
    {
        $payRefundType = $goodsRefundType = $payRefundData = $goodsRefundData = $refundData = [];
        $refund = $this->container->make(RefundShoppingInterface::class)->detail($map, true);
        foreach ($refund as $value) {
            if ($value['card_amount'] > 0) {
                $payRefundData[Shopping::MEMBER_CARD][] = $value['card_amount'];
            }
            $payRefundData[$value['pay_type']][] = $value['amount'];
            $goodsRefundData[] = $value['detail'];
        }
        foreach ($payRefundData as $keys => $pay) {
            $key = $this->getPayType($keys);
            $payRefundType[$key] = array_sum($pay);
        }
        foreach ($goodsRefundData as $goods) {
            foreach ($goods as $good) {
                $refundData[$good['goods_id']][] = [
                    'name' => $good['zh_name'], 'counts' => $good['counts'],
                    'totalPrice' => $good['price'] * $good['counts']
                ];
            }
        }
        $totalPrice = 0;
        foreach ($refundData as $k => $val) {
            $amount[$k] = $counts[$k] = 0;
            $name[$k] = $val[0]['name'];
            foreach ($val as $v) {
                $amount[$k] += $v['totalPrice'];
                $counts[$k] += $v['counts'];
            }
            $totalPrice += $amount[$k];
            $goodsRefundType[] = [
                'name' => $name[$k], 'amount' => $amount[$k], 'counts' => $counts[$k]
            ];
        }

        return ['payRefundType' => $payRefundType, 'goodsRefundType' => $goodsRefundType, 'totalPrice' => $totalPrice];
    }

    /**
     * 获取充值数据
     *
     * @param $map
     * @return array
     */
    public function getRecharge($map)
    {
        $recharge = $this->container->make(MemberRechargeInterface::class)->detailByNumber($map);
        $rechargeMoney = 0;
        foreach ($recharge as $val) {
            if ($val['type'] ==1 ) $rechargeMoney += $val['money'];
        }

        return ['rechargeMoney' => $rechargeMoney];
    }

    /**
     * @param $val
     * @return string
     */
    protected function getPayType($val)
    {
        switch ($val) {
            case Shopping::BANK_CARD;
                $key = 'bankCard';
                break;
            case Shopping::INTEGRAL;
                $key = 'integral';
                break;
            case Shopping::WE_CHAT;
                $key = 'weChat';
                break;
            case Shopping::PAY_PAL;
                $key = 'payPal';
                break;
            case Shopping::MEMBER_CARD;
                $key = 'memberCard';
                break;
            case Shopping::COUPON;
                $key = 'coupon';
                break;
            default:
                $key = 'rmb';
                break;
        }

        return $key;
    }
}